home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / System / Sample 2.4 Think C distribution / mssg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-25  |  17.4 KB  |  641 lines  |  [TEXT/KAHL]

  1. /*______________________________________________________________________
  2.  
  3.     mssg.c - Virus Message Module.
  4.     
  5.     Copyright © 1988, 1989, 1990 Northwestern University.  Permission is granted
  6.     to use this code in your own projects, provided you give credit to both
  7.     John Norstad and Northwestern University in your about box or document.
  8.     
  9.     This module contains the scan begin and end routines, and a variety
  10.     of helper routines for issuing messages to the report.  It also
  11.     maintains the three counters in the main window.
  12. _____________________________________________________________________*/
  13.  
  14. #include <string.h>
  15.  
  16. #include "utl.h"
  17. #include "rep.h"
  18. #include "vol.h"
  19. #include "rez.h"
  20. #include "glob.h"
  21. #include "mssg.h"
  22.  
  23. #define nil 0
  24.  
  25. /*______________________________________________________________________
  26.  
  27.     Global Types and Variables.
  28. _____________________________________________________________________*/
  29.  
  30.  
  31. typedef struct TagTableEntry {
  32.     short        reportLineNum;
  33.     short        tag;
  34. } TagTableEntry;
  35.  
  36.  
  37. static TagTableEntry        (**TagTable)[] = nil;    /* handle to tag table */
  38. static short                NTags = 0;                    /* number of tags */
  39. static short                NAlloc = 0;                    /* number of allocated
  40.                                                                     tag table entries */
  41. static short                CounterTop;                    /* top coord of counters */
  42. static short                CounterRight;                /* right coord of counters */
  43. static Str255                Line1;                        /* unplugged message line */
  44. static Str255                Line2;                        /* plugged message line */
  45.  
  46.  
  47. /*______________________________________________________________________
  48.  
  49.     RecordTag - Record a New Tag.
  50.     
  51.     Entry:    tag = tag to be recorded.  If the tag is zero or if it
  52.                 does not appear in the TAG resource it is not
  53.                 recorded.
  54.                     
  55.     Exit:        current report line number and corresponding tag
  56.                 recorded in table.
  57. _____________________________________________________________________*/
  58.  
  59.  
  60. static void RecordTag (short tag)
  61.  
  62. {
  63.     TagTableEntry        tagEntry;    /* new entry for tag table */
  64.     
  65.     if (!tag || !rep_Tag(tagID, tag)) return;
  66.     tagEntry.reportLineNum = rep_GetSize(Report);
  67.     tagEntry.tag = tag;
  68.     
  69.     /* Allocate more space in tag table if necessary. */
  70.     
  71.     if (NTags >= NAlloc) {
  72.         if (!TagTable) {
  73.             TagTable = (TagTableEntry(**)[])NewHandle(10*sizeof(TagTableEntry));
  74.             NAlloc = 10;
  75.         } else {
  76.             SetHandleSize((Handle)TagTable, 
  77.                 GetHandleSize((Handle)TagTable) + 10*sizeof(TagTableEntry));
  78.             NAlloc += 10;
  79.         };
  80.     };
  81.     
  82.     /* Record new tag table entry. */
  83.     
  84.     (**TagTable)[NTags] = tagEntry;
  85.     NTags++;
  86. }
  87.  
  88. /*______________________________________________________________________
  89.  
  90.     mssg_LookupTag - Lookup a Tag.
  91.     
  92.     Entry:    repLine = line number in report of error message.
  93.                     
  94.     Exit:        function result = tag of doc text of error
  95.                 message description, or -1 if the report line number is
  96.                 not an error message.
  97. _____________________________________________________________________*/
  98.  
  99.  
  100. short mssg_LookupTag (short repLine)
  101.  
  102. {
  103.     short            i;
  104.     
  105.     for (i = 0; i < NTags; i++) {
  106.         if ((**TagTable)[i].reportLineNum == repLine) 
  107.             return (**TagTable)[i].tag;
  108.     };
  109.     return -1;
  110. }
  111.  
  112. /*______________________________________________________________________
  113.  
  114.     mssg_ClearTags - Clear the Tag Table.
  115.     
  116.     This routine should be called whenever the report is cleared.
  117. _____________________________________________________________________*/
  118.  
  119.  
  120. void mssg_ClearTags (void)
  121.  
  122. {
  123.     if (TagTable) {
  124.         DisposHandle((Handle)TagTable);
  125.         TagTable = nil;
  126.     };
  127.     NTags = NAlloc = 0;
  128. }
  129.  
  130. /*______________________________________________________________________
  131.  
  132.     mssg_M0 - Issue a Report Message with 0 Parameters.
  133.     mssg_M1 - Issue a Report Message with 1 Parameter.
  134.     mssg_M2 - Issue a Report Message with 2 Parameters.
  135.     mssg_M2_Tag - Issue a Report Message with 2 Parameters and a tag.
  136.     mssg_Continue - Issue a Report Message Continuation Line.
  137.     mssg_Blank - Issue a Blank Line to the Report.
  138.     
  139.     Entry:        strInd = index in STR# of message template.
  140.                     p0 = pointer to param 1.
  141.                     p1 = pointer to param 2.
  142.                     msgNum = message number = index in STR# of first line
  143.                         of error message.
  144.                     tag = document tag.
  145. _____________________________________________________________________*/
  146.  
  147.  
  148. void mssg_M0 (short strInd)
  149.  
  150. {
  151.     GetIndString(Line1, strListID, strInd);
  152.     RecordTag(strInd);
  153.     rep_Append(Report, &Line1, true, true);
  154. }
  155.  
  156.  
  157. void mssg_M1 (short strInd, Str255 *p0)
  158.  
  159. {
  160.     GetIndString(Line1, strListID, strInd);
  161.     utl_PlugParams(&Line1, &Line2, p0, nil, nil, nil);
  162.     RecordTag(strInd);
  163.     rep_Append(Report, &Line2, true, true);
  164. }
  165.  
  166.  
  167. void mssg_M2 (short strInd, Str255 *p0, Str255 *p1)
  168.  
  169. {
  170.     GetIndString(Line1, strListID, strInd);
  171.     utl_PlugParams(&Line1, &Line2, p0, p1, nil, nil);
  172.     RecordTag(strInd);
  173.     rep_Append(Report, &Line2, true, true);
  174. }
  175.  
  176.  
  177. void mssg_M2_Tag (short strInd, Str255 *p0, Str255 *p1, short tag)
  178.  
  179. {
  180.     GetIndString(Line1, strListID, strInd);
  181.     utl_PlugParams(&Line1, &Line2, p0, p1, nil, nil);
  182.     RecordTag(tag);
  183.     rep_Append(Report, &Line2, true, true);
  184. }
  185.  
  186.  
  187. void mssg_Continue (short strInd, short msgNum)
  188.  
  189. {
  190.     GetIndString(Line1, strListID, strInd);
  191.     RecordTag(msgNum);
  192.     rep_Append(Report, &Line1, true, true);
  193. }
  194.  
  195.  
  196. void mssg_Blank (void)
  197. {
  198.     rep_Append(Report, (Str255 *)"\p", true, true);
  199. }
  200.  
  201. /*______________________________________________________________________
  202.  
  203.     PrintPath - Print Indented Path Name.
  204.     
  205.     Entry:    folderList = handle to folder list.
  206.                     
  207.     Exit:        level = indentation level for next element of path.
  208.                 tag = document tag to be associated with each line of the
  209.                     path name list in the report, or 0 if none.
  210.     
  211.     This function calls itself recursively to output the folder list
  212.     in reverse order.
  213. _____________________________________________________________________*/
  214.  
  215.  
  216. static void PrintPath (scn_FListElHandle folderList, short *level, short tag)
  217.  
  218. {
  219.     short                myLevel;            /* my level */
  220.     unsigned char    *p;                /* pointer into Line1 */
  221.     short                len;                /* length of folder name */
  222.     
  223.     if (*(**folderList).name) {
  224.         PrintPath((**folderList).next, &myLevel, tag);
  225.         *level = myLevel + 3;
  226.         p = &Line1[1];
  227.         while (myLevel--) *p++ = ' ';
  228.         len = *(**folderList).name;
  229.         if (p + len >= &Line1[256]) len = &Line1[256] - p;
  230.         memcpy(p, (**folderList).name + 1, len);
  231.         Line1[0] = p - Line1 - 1 + len;
  232.         RecordTag(tag);
  233.         rep_Append(Report, &Line1, true, true);
  234.     } else {
  235.         *level = 0;
  236.     }
  237. }        
  238.  
  239. /*______________________________________________________________________
  240.  
  241.     mssg_PrintFileName - Print the File Name.
  242.     
  243.     Entry:    folderList = handle to folder list.
  244.                 pBlock = pointer to PBGetCatInfo param block.
  245.                 tag = document tag to be associated with each line of the
  246.                     path name list in the report, or 0 if none.
  247. _____________________________________________________________________*/
  248.  
  249.  
  250. void mssg_PrintFileName (scn_FListElHandle folderList, 
  251.     CInfoPBRec *pBlock, short tag)
  252.  
  253. {
  254.     short                    indentLevel;        /* indentation level */
  255.     unsigned char        *pLine;                /* pointer into message line */
  256.     short                    fileNameLen;        /* length of file name */
  257.  
  258.     if (CurScanKind == fileScan) return;
  259.     rep_Append(Report, (Str255 *)"\p--------------------------------------------", 
  260.         true, true);
  261.     PrintPath(folderList, &indentLevel, tag);
  262.     pLine = &Line1[1];
  263.     while (indentLevel--) *pLine++ = ' ';
  264.     fileNameLen = pBlock->hFileInfo.ioNamePtr[0];
  265.     if (pLine + fileNameLen >= &Line1[256])
  266.         fileNameLen = &Line1[256] - pLine;
  267.     memcpy(pLine, pBlock->hFileInfo.ioNamePtr + 1, fileNameLen);
  268.     Line1[0] = pLine - &Line1[0] - 1 + fileNameLen;
  269.     RecordTag(tag);
  270.     rep_Append(Report, &Line1, true, true);
  271. }
  272.  
  273. /*______________________________________________________________________
  274.  
  275.     PrintSum - Print Summary Line.
  276.     
  277.     Entry:        theNum = longword summary counter.
  278.                     theMsg = index in STR# resource of plural form of message, 
  279.                         followed by singular form of message. 
  280.                     thePlug = pointer to ^1 plug, or nil if none.
  281. _____________________________________________________________________*/
  282.  
  283.  
  284. static void PrintSum (long theNum, short theMsg, Str255 *thePlug)
  285.  
  286. {
  287.     Str255            decNum;            /* converted number */
  288.     
  289.     NumToString(theNum, decNum);
  290.     mssg_M2(theMsg + ((theNum==1) ? 1 : 0), &decNum, thePlug);
  291. }
  292.  
  293. /*______________________________________________________________________
  294.  
  295.     mssg_CheckAccess - Check Directory Access Privileges.
  296.     
  297.     Entry:    accessRights = ioACUser field from PBGetCatInfo param
  298.                     block.  (see IM V-391).
  299.                 folderList = handle to folder list to be printed, or
  300.                     nil to inhibit printing of folder list.
  301.                 pBlock = pointer to PBGetCatInfo param block
  302.                     if folderList != nil.
  303. _____________________________________________________________________*/
  304.  
  305.  
  306. void mssg_CheckAccess (char accessRights, 
  307.     scn_FListElHandle folderList, CInfoPBRec *pBlock)
  308.     
  309. {
  310.     short            firstMsg;            /* index of first message */
  311.  
  312.     /* Return if user has both See Files and See Folders access
  313.         privileges. */
  314.  
  315.     if (!(accessRights &= 3)) return;
  316.     
  317.     /* Print folder path if folderList != nil. */
  318.     
  319.     firstMsg = noPrivs1 + 3*(accessRights-1);
  320.     if (folderList) {
  321.         mssg_PrintFileName(folderList, pBlock, firstMsg);
  322.     };
  323.     
  324.     /* Issue error message. */
  325.     
  326.     mssg_M0(firstMsg);
  327.     mssg_Continue(firstMsg+1, firstMsg);
  328.     mssg_Continue(firstMsg+2, firstMsg);
  329.     TotErrors++;
  330.     mssg_BumpCounter(2);
  331.     TotNoAccess++;
  332. }
  333.  
  334. /*______________________________________________________________________
  335.  
  336.     mssg_Begin - Begin a Scan.
  337.     
  338.     Entry            disinfect = true if disinfection run.
  339.                     dirID = directory id of folder if folder scan.
  340.                     fName = pointer to file name if file scan.
  341.                     fVRefNum = vol or wd ref num of folder containing file
  342.                         if file scan.
  343.                     volRefNum = vol ref num of vol if volume scan, or vol ref
  344.                         num of vol containing file or folder if file or folder 
  345.                         scan.
  346.                     counterTop = top coord of main window counters.
  347.                     counterRight = right coord of main window counters.
  348. _____________________________________________________________________*/
  349.  
  350.  
  351. void mssg_Begin (Boolean disinfect, long dirID, Str255 *fName, 
  352.     short fVRefNum, short volRefNum, short counterTop, short counterRight)
  353.  
  354. {
  355.     long    secs;                                /* current date/time */
  356.     Str255            nowDate;                /* current date */
  357.     Str255            nowTime;                /* current time */
  358.     scn_FListElHandle    folderList;        /* handle to first el in folder list */
  359.     scn_FListElHandle    newEl;            /* handle to new el for folder list */
  360.     scn_FListElHandle    lastEl;            /* handle to last el in folder list */
  361.     WDPBRec            wdBlock;                /* working directory info block */
  362.     long                curDir;                /* directory id */
  363.     Str255            dirName;                /* directory name */
  364.     CInfoPBRec        dBlock;                /* directory info block */
  365.     short                level;                /* indentation level */
  366.     Boolean            firstDir;            /* true if first directory */
  367.     char                accessRights;        /* directory access rights */
  368.  
  369.     /* Initialize global variables. */
  370.     
  371.     TotFiles = TotErrors = TotInfected = TotNoAccess = 0;
  372.     CounterTop = counterTop;
  373.     CounterRight = counterRight;
  374.     
  375.     /* Write the report header lines. */
  376.     
  377.     mssg_Blank();
  378.     rep_Append(Report, (Str255 *)"\p===========================================",
  379.         true, true);
  380.     mssg_Blank();
  381.     
  382.     /* Write the volume name, folder path list, or file path list.
  383.         For folders and files we build a temporary linked list of
  384.         folder names for use by PrintPath. */
  385.     
  386.     if (utl_VolIsMFS(volRefNum)) {
  387.         vol_GetName(&Line1);
  388.         rep_Append(Report, &Line1, true, true);
  389.         if (CurScanKind == fileScan) {
  390.             Line1[0] = (*fName)[3];
  391.             Line1[1] = ' ';
  392.             Line1[2] = ' ';
  393.             Line1[3] = ' ';
  394.             memcpy(&Line1[4], &((*fName)[1]), (*fName)[0]);
  395.             rep_Append(Report, &Line1, true, true);
  396.         };
  397.     } else {
  398.         folderList = lastEl = nil;
  399.         if (CurScanKind == fileScan) {
  400.             wdBlock.ioNamePtr = nil;
  401.             wdBlock.ioVRefNum = fVRefNum;
  402.             wdBlock.ioWDIndex = 0;
  403.             wdBlock.ioWDProcID = 0;
  404.             wdBlock.ioWDVRefNum = 0;
  405.             (void) PBGetWDInfo(&wdBlock, false);
  406.             curDir = wdBlock.ioWDDirID;
  407.             newEl = (scn_FListElHandle)NewHandle(sizeof(scn_FListEl));
  408.             (**newEl).next = nil;
  409.             utl_CopyPString((Str255 *)(**newEl).name, fName);
  410.             folderList = lastEl = newEl;
  411.         } else if (CurScanKind == foldScan) { 
  412.             curDir = dirID;
  413.         } else {
  414.             curDir = fsRtDirID;
  415.         };
  416.         firstDir = true;
  417.         while (true) {
  418.             dBlock.dirInfo.ioNamePtr = (StringPtr)&dirName;
  419.             dBlock.dirInfo.ioVRefNum = volRefNum;
  420.             dBlock.dirInfo.ioFDirIndex = -1;
  421.             dBlock.dirInfo.ioDrDirID = curDir;
  422.             /* dBlock.dirInfo.ioACUser = 0; */
  423.             *(&dBlock.dirInfo.ioFlAttrib+1) = 0;
  424.             (void) PBGetCatInfo((CInfoPBPtr)&dBlock, false);
  425.             if (firstDir) {
  426.                 /* accessRights = dBlock.dirInfo.ioACUser; */
  427.                 accessRights = *(&dBlock.dirInfo.ioFlAttrib+1);
  428.                 firstDir = false;
  429.             };
  430.             newEl = (scn_FListElHandle)NewHandle(sizeof(scn_FListEl));
  431.             (**newEl).next = nil;
  432.             utl_CopyPString((Str255 *)(**newEl).name, &dirName);
  433.             if (folderList) {
  434.                 (**lastEl).next = newEl;
  435.                 lastEl = newEl;
  436.             } else {
  437.                 folderList = lastEl = newEl;
  438.             };
  439.             if (curDir == fsRtDirID) break;
  440.             curDir = dBlock.dirInfo.ioDrParID;
  441.         };
  442.         newEl = (scn_FListElHandle)NewHandle(sizeof(scn_FListEl));
  443.         (**newEl).next = nil;
  444.         *(**newEl).name = 0;
  445.         if (lastEl) {
  446.             (**lastEl).next = newEl;
  447.         } else {
  448.             folderList = newEl;
  449.         };
  450.         PrintPath(folderList, &level, 0);
  451.         while (folderList) {
  452.             newEl = (**folderList).next;
  453.             DisposHandle((Handle)folderList);
  454.             folderList = newEl;
  455.         };
  456.         if (CurScanKind != fileScan) 
  457.             mssg_CheckAccess(accessRights, nil, nil);
  458.     };
  459.     
  460.     /* Write the final header messages. */
  461.     
  462.     if (CurScanKind == foldScan) {
  463.         mssg_M0(disinfect ? fdStartStr : fsStartStr);
  464.     } else if (CurScanKind == fileScan) {
  465.         mssg_M0(disinfect ? xdStartStr : xsStartStr);
  466.     } else {
  467.         mssg_M0(disinfect ? ddStartStr : dsStartStr);
  468.     }
  469.     GetDateTime(&secs);
  470.     IUDateString(secs, shortDate, (StringPtr)&nowDate);
  471.     IUTimeString(secs, true, (StringPtr)&nowTime);
  472.     mssg_M2(scanDateStr, &nowDate, &nowTime);
  473. }
  474.  
  475. /*______________________________________________________________________
  476.  
  477.     mssg_End - End a Scan.
  478.     
  479.     Entry:        disinfect = true if disinfection run.
  480.                     canceled = true if scan canceled.
  481.                     
  482.     Exit:            *infected = true if infected file found.
  483.                     *sysInfected = true if infected file found in currently
  484.                         active system folder.
  485. _____________________________________________________________________*/
  486.  
  487.  
  488. void mssg_End (Boolean disinfect, 
  489.     Boolean canceled, Boolean *infected, Boolean *sysInfected)
  490.  
  491. {
  492.     long    secs;                                /* current date/time */
  493.     Str255            date;                    /* date */
  494.     Str255            time;                    /* time */
  495.     
  496.     /* Set the infected and sysinfected flag. */
  497.     
  498.     *infected = TotInfected > 0;
  499.     *sysInfected = false;
  500.  
  501.     /* If scan canceled write canceled message. */
  502.     
  503.     if (canceled) {
  504.         mssg_Blank();
  505.         mssg_M0(cancelStr);
  506.         return;
  507.     };
  508.  
  509.     /* Write the "scan complete" report lines. */
  510.     
  511.     if (TotInfected || TotErrors) {
  512.         rep_Append(Report, (Str255 *)"\p--------------------------------------------", 
  513.             true, true);
  514.     };
  515.     if (CurScanKind == foldScan) {
  516.         mssg_M0(disinfect ? fdEndStr : fsEndStr);
  517.     } else if (CurScanKind == fileScan) {
  518.         mssg_M0(disinfect ? xdEndStr : xsEndStr);
  519.     } else {
  520.         mssg_M0(disinfect ? ddEndStr : dsEndStr);
  521.     }
  522.     GetDateTime(&secs);
  523.     IUDateString(secs, shortDate, (StringPtr)&date);
  524.     IUTimeString(secs, true, (StringPtr)&time);
  525.     mssg_M2(scanDateStr, &date, &time);
  526.     
  527.     /* Write the summary report lines. */
  528.     
  529.     if (TotInfected || TotErrors) {
  530.         mssg_Blank();
  531.         mssg_M0(summaryStr);
  532.         mssg_Blank();
  533.         PrintSum(TotFiles, totFilesStr, nil);
  534.         PrintSum(TotErrors, totErrorsStr, nil);
  535.         PrintSum(TotInfected, totInfectedStr, nil);
  536.         if (TotNoAccess) {
  537.             mssg_Blank();
  538.             mssg_M0(noPrivs13);
  539.             mssg_Continue(noPrivs14, noPrivs13);
  540.             mssg_Continue(noPrivs15, noPrivs13);
  541.         };
  542.     } else {
  543.         if (CurScanKind == fileScan) {
  544.         } else { 
  545.             PrintSum(TotFiles, totFilesStr, nil);
  546.             mssg_Blank();
  547.         };
  548.     };
  549.     
  550.     /* If any error messages were issued refer the user to the
  551.         document for more details. */
  552.         
  553.     if (TotErrors) {
  554.         mssg_Blank();
  555.         mssg_M0(errNoteStr1);
  556.         mssg_Continue(errNoteStr2, errNoteStr1);
  557.         mssg_Continue(errNoteStr3, errNoteStr1);
  558.     };
  559. }
  560.  
  561. /*______________________________________________________________________
  562.  
  563.     mssg_BumpCounter - Increment a counter.
  564.     
  565.     Entry:        counter = 0 to increment number of files scanned.
  566.                     counter = 1 to increment number of infected files.
  567.                     counter = 2 to increment number of errors.
  568. _____________________________________________________________________*/
  569.  
  570.  
  571. void mssg_BumpCounter (short counter)
  572.  
  573. {
  574.     long                x;                /* counter value to be redrawn */
  575.     short                h;                /* horizontal coord of counter */
  576.     short                v;                /* vertical coord of counter */
  577.     Str255            str;            /* string to be drawn */
  578.     short                resFile;        /* saved current resource file */
  579.  
  580.     switch (counter) {
  581.         case 0:
  582.             NumScanned++;
  583.             x = NumScanned;
  584.             break;
  585.         case 1:
  586.             NumInfected++;
  587.             x = NumInfected;
  588.             break;
  589.         case 2:
  590.             NumErrors++;
  591.             x = NumErrors;
  592.             break;
  593.     };
  594.     v = CounterTop + 12*(counter+1);
  595.     h = CounterRight + 5;
  596.     MoveTo(h, v);
  597.     NumToString(x, str);
  598.     resFile = CurResFile();
  599.     UseResFile(0);
  600.     TextMode(srcCopy);
  601.     DrawString(str);
  602.     TextMode(srcOr);
  603.     UseResFile(resFile);
  604. }
  605.  
  606. /*______________________________________________________________________
  607.  
  608.     mssg_ClearCounters - Clear counters.
  609.     
  610.     Entry:        counterTop = top coord of main window counters.
  611.                     counterRight = right coord of main window counters.
  612. _____________________________________________________________________*/
  613.  
  614.  
  615. void mssg_ClearCounters (short counterTop, short counterRight)
  616.  
  617. {
  618.     Rect            inval;            /* rectangle to be invalidated */
  619.  
  620.     NumScanned = NumInfected = NumErrors = 0;
  621.     SetRect(&inval, counterRight+5, counterTop, counterRight+55, counterTop+36);
  622.     InvalRect(&inval);
  623. }
  624.  
  625. /*______________________________________________________________________
  626.  
  627.     mssg_BadDisk - Issue Bad Disk Error Message.
  628. _____________________________________________________________________*/
  629.  
  630.  
  631. void mssg_BadDisk (void)
  632.  
  633. {
  634.     mssg_Blank();
  635.     rep_Append(Report, (Str255 *)"\p===========================================",
  636.         true, true);
  637.     mssg_Blank();
  638.     mssg_M0(badDiskStr1);
  639.     mssg_Continue(badDiskStr2, badDiskStr1);
  640. }
  641.